#include "mprpcchannel.h"
#include "rpcheader.pb.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "mprpcappliaction.h"
#include <unistd.h>
#include "zookeeperutil.h"

void MprpcChannel::CallMethod(const google::protobuf::MethodDescriptor *method,
                              google::protobuf::RpcController *controller,
                              const google::protobuf::Message *request,
                              google::protobuf::Message *response,
                              google::protobuf::Closure *done)
{
    const google::protobuf::ServiceDescriptor *service_desc = method->service();
    std::string service_name = service_desc->name();
    std::string method_name = method->name();

    std::string args_str;
    uint32_t args_size = 0;
    if (request->SerializeToString(&args_str))
    {
        args_size = args_str.size();
    }
    else
    {
        controller->SetFailed("serialize request error!");
        // std::cout<< "serialize request error!" << std::endl;
        return;
    }

    mprpc::RpcHeader rpcheader;
    rpcheader.set_service_name(service_name);
    rpcheader.set_method_name(method_name);
    rpcheader.set_args_size(args_size);

    std::string rpc_header_str;
    uint32_t header_size = 0;
    if (rpcheader.SerializeToString(&rpc_header_str))
    {
        header_size = rpc_header_str.size();
    }
    else
    {
        controller->SetFailed("serialize rpcheader is error!");
        // std::cout << "serialize rpcheader is error!" << std::endl;
        return;
    }

    // 组织发送rpc请求的字符串
    std::string send_rpc_str;
    send_rpc_str.insert(0, std::string((const char *)&header_size, 4));
    send_rpc_str += rpc_header_str;
    send_rpc_str += args_str;

    std::cout << "======================================================" << std::endl;
    std::cout << "header_size: " << header_size << std::endl;
    std::cout << "rpc_header_str: " << rpc_header_str << std::endl;
    std::cout << "service_name: " << service_name << std::endl;
    std::cout << "method_name: " << method_name << std::endl;
    std::cout << "args_size: " << args_size << std::endl;
    std::cout << "args_str: " << args_str << std::endl;
    std::cout << "send_rpc_str: " << send_rpc_str << std::endl;
    std::cout << "======================================================" << std::endl;
    // 使用tcp来发送请求给服务端

    int clientfd = socket(AF_INET, SOCK_STREAM, 0);
    if (clientfd == -1)
    {
        controller->SetFailed("create socket error! errno: " + std::to_string(errno));
        // std::cout << "create socket error! errno: " << errno << std::endl;
        return;
    }

    // std::string ip = MprpcApplication::GetInstance().GetConfig().Load("rpcserverip");
    // uint16_t port = atoi(MprpcApplication::GetInstance().GetConfig().Load("rpcserverport").c_str());
    // 更改为从zk上获取ip和port信息
    ZkClient zkCli;
    zkCli.Start();
    std::string method_path = "/" + service_name + "/" + method_name;
    std::string ip_port = zkCli.GetData(method_path.c_str());
    if (ip_port == "")
    {
        controller->SetFailed(method_path + " is not exist!");
        return;
    }
    int idx = ip_port.find(':');
    if (idx == -1)
    {
        controller->SetFailed(method_path + " address is invalid!");
        return;
    }
    std::string ip = ip_port.substr(0, idx);
    uint16_t port = atoi(ip_port.substr(idx + 1, ip_port.size() - idx).c_str());

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(ip.c_str());

    // connect
    if (connect(clientfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        controller->SetFailed("connect error! errno: " + std::to_string(errno));
        // std::cout << "connect error! errno: " << errno << std::endl;
        close(clientfd);
        return;
    };

    // send
    if (send(clientfd, send_rpc_str.c_str(), send_rpc_str.size(), 0) == -1)
    {
        controller->SetFailed("send error! errno: " + std::to_string(errno));
        // std::cout << "send error! errno: " << errno << std::endl;
        close(clientfd);
        return;
    }

    // recv
    char recv_buf[1024] = {0};
    int recv_size = 0;
    if ((recv_size = recv(clientfd, recv_buf, 1024, 0)) == -1)
    {
        controller->SetFailed("recv error! errno: " + std::to_string(errno));
        // std::cout << "recv error! errno: " << errno << std::endl;
        close(clientfd);
        return;
    }

    // 反序列化rpc调用的响应数据
    // std::string response_str(recv_buf, 0, recv_size);
    // if (!response->ParseFromString(response_str))
    if (!response->ParseFromArray(recv_buf, recv_size))
    {
        controller->SetFailed("parse error! response_str: " + std::string(recv_buf));
        // std::cout << "parse error! response_str: " << recv_buf << std::endl;
        close(clientfd);
        return;
    }
    close(clientfd);
}